home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / cuj9205.zip / 1005010A < prev    next >
Text File  |  1992-06-02  |  2KB  |  84 lines

  1.  
  2. Listing 1 -- xstoul.c
  3.  
  4.  
  5. /* _Stoul function */
  6. #include <stdlib.h>
  7. #include <ctype.h>
  8. #include <errno.h>
  9. #include <limits.h>
  10. #include <stddef.h>
  11. #include <string.h>
  12.  
  13.         /* macros */
  14. #define BASE_MAX    36    /* largest valid base */
  15.         /* static data */
  16. static const char digits[] = {    /* valid digits */
  17.     "0123456789abcdefghijklmnopqrstuvwxyz"};
  18. static const char ndigs[BASE_MAX+1] = {    /* 32-bits! */
  19.     0, 0, 33, 21, 17, 14, 13, 12, 11, 11,
  20.     10, 10, 9, 9, 9, 9, 9, 8, 8, 8,
  21.     8, 8, 8, 8, 7, 7, 7, 7, 7, 7,
  22.     7, 7, 7, 7, 7, 7, 7,};
  23.  
  24. unsigned long _Stoul(const char *s, char **endptr, int base)
  25.     {    /* convert string to unsigned long, with checking */
  26.     const char *sc, *sd;
  27.     const char *s1, *s2;
  28.     char sign;
  29.     ptrdiff_t n;
  30.     unsigned long x, y;
  31.  
  32.     for (sc = s; isspace(*sc); ++sc)
  33.         ;
  34.     sign = *sc == '-' || *sc == '+' ? *sc++ : '+';
  35.     if (base < 0 || base == 1 || BASE_MAX < base)
  36.         {    /* silly base */
  37.         if (endptr)
  38.             *endptr = (char *)s;
  39.         return (0);
  40.         }
  41.     else if (base)
  42.         {    /* strip 0x or 0X */
  43.         if (base == 16 && *sc == '0'
  44.             && (sc[1] == 'x' || sc[1] == 'X'))
  45.             sc += 2;
  46.         }
  47.     else if (*sc != '0')
  48.         base = 10;
  49.     else if (sc[1] == 'x' || sc[1] == 'X')
  50.         base = 16, sc += 2;
  51.     else
  52.         base = 8;
  53.     for (s1 = sc; *sc == '0'; ++sc)
  54.         ;    /* skip leading zeros */
  55.     x = 0;
  56.     for (s2 = sc; (sd = (char *)memchr(digits,
  57.         tolower(*sc), base)) != NULL; ++sc)
  58.         {    /* accumulate digits */
  59.         y = x;    /* for overflow checking */
  60.         x = x * base + (sd - digits);
  61.         }
  62.     if (s1 == sc)
  63.         {    /* check string validity */
  64.         if (endptr)
  65.             *endptr = (char *)s;
  66.         return (0);
  67.         }
  68.     n = sc - s2 - ndigs[base];
  69.     if (n < 0)
  70.         ;
  71.     else if (0 < n || x < x - sc[-1]
  72.         || (x - sc[-1]) / base != y)
  73.         {    /* overflow */
  74.         errno = ERANGE;
  75.         x = ULONG_MAX;
  76.         }
  77.     if (sign == '-')    /* get final value */
  78.         x = -x;
  79.     if (endptr)
  80.         *endptr = (char *)sc;
  81.     return (x);
  82.     }
  83.  
  84.